﻿using System;
using System.Data;
using System.Data.Common;

namespace Mind.Data
{
    public class ColumnInfo
    {
        public string ColumnName { get; private set; }
        public bool IsKey { get; private set; }
        public DbType ColumnType { get; private set; }
        public Type PropertyType { get; private set; }
        public bool IsNullable { get; private set; }
        public bool AutoIncrement { get; private set; }
        public bool IsNameProperty { get { return NamePropertyIndex >= 0; } }
        public int NamePropertyIndex { get; private set; }
        public object DefaultValue { get; private set; }
        public string UniqueAlias { get {return String.Format("{0}_{1}", Schema.TableName, this.ColumnName); } }
        public ISchema Schema { get; internal set; }
        internal LockupInfo LockupInfo { get; set; }

        #region Normal Columns
        /// <summary>
        /// Cria uma coluna que:
        /// - Aceita NULL
        /// - Não é chave
        /// - Não é FK
        /// - Não é descritiva (Não aparece no ToString())
        /// - Não é auto incremento
        /// - Valor padrão é NULL
        /// </summary>
        /// <param name="columnName">Nome da coluna</param>
        /// <param name="type">Tipo da coluna</param>
        /// <returns>A instância da coluna </returns>
        public static ColumnInfo CreateNormalColumn(string columnName, Type type)
        {
            return new ColumnInfo(columnName, type);
        }

        /// <summary>
        /// Cria uma coluna que:
        /// - Não é chave
        /// - Não é FK
        /// - Não é descritiva (Não aparece no ToString())
        /// - Não é auto incremento
        /// - Valor padrão é NULL
        /// </summary>
        /// <param name="columnName">Nome da coluna</param>
        /// <param name="type">Tipo da coluna</param>
        /// <param name="nullable">Se aceita ou não NULL</param>
        /// <returns>A instância da coluna </returns>
        public static ColumnInfo CreateNormalColumn(string columnName, Type type, bool nullable)
        {
            return new ColumnInfo(columnName, type, nullable);
        }


        /// <summary>
        /// Cria uma coluna que:
        /// - Não é chave
        /// - Não é FK
        /// - Não é auto incremento
        /// - Valor padrão é NULL
        /// </summary>
        /// <param name="columnName">Nome da coluna</param>
        /// <param name="type">Tipo da coluna</param>
        /// <param name="nullable">Se aceita ou não NULL</param>
        /// <param name="namePropertyIndex">Se deve aparecer no ToString() passe a posição de preferência, se não, null</param>
        /// <returns>A instância da coluna </returns>
        public static ColumnInfo CreateNormalColumn(string columnName, Type type, bool nullable, int? namePropertyIndex)
        {
            return new ColumnInfo(columnName, type, nullable, namePropertyIndex);
        }

        /// <summary>
        /// Cria uma coluna que:
        /// - Não é chave
        /// - Não é FK
        /// - Não é auto incremento
        /// - Valor padrão é NULL
        /// </summary>
        /// <param name="columnName">Nome da coluna</param>
        /// <param name="type">Tipo da coluna</param>
        /// <param name="nullable">Se aceita ou não NULL</param>
        /// <param name="namePropertyIndex">Se deve aparecer no ToString() passe a posição de preferência, se não, null</param>
        /// <returns>A instância da coluna </returns>
        public static ColumnInfo CreateNormalColumn(string columnName, Type type, bool nullable, int? namePropertyIndex, object defaultValue)
        {
            return new ColumnInfo(columnName, type, nullable, false, false, namePropertyIndex, defaultValue);
        }

        #endregion

        #region Key Column

        /// <summary>
        /// Cria uma coluna que:
        /// - É KEY
        /// - Não é FK
        /// - Não é descritiva (Não aparece no ToString())
        /// - É auto incremento
        /// ATENÇÃO: O valor padrão para chave sempre é NULL
        /// </summary>
        /// <param name="columnName">Nome da coluna</param>
        /// <param name="type">Tipo da coluna</param>
        /// <returns>A instância da coluna </returns>
        public static ColumnInfo CreatePrimaryKeyColumn(string columnName, Type type)
        {
            return new ColumnInfo(columnName, type, true, true);
        }

        /// <summary>
        /// Cria uma coluna que:
        /// - É KEY
        /// - Não é FK
        /// - Não é descritiva (Não aparece no ToString())
        /// ATENÇÃO: O valor padrão para chave sempre é NULL
        /// </summary>
        /// <param name="columnName">Nome da coluna</param>
        /// <param name="type">Tipo da coluna</param>
        /// <returns>A instância da coluna </returns>
        public static ColumnInfo CreatePrimaryKeyColumn(string columnName, Type type, bool autoIncremento)
        {
            return new ColumnInfo(columnName, type, true, autoIncremento);
        }


        /// <summary>
        /// Cria uma coluna que:
        /// - É KEY
        /// - Não é FK
        /// ATENÇÃO: O valor padrão para chave sempre é NULL
        /// </summary>
        /// <param name="columnName">Nome da coluna</param>
        /// <param name="type">Tipo da coluna</param>
        /// <returns>A instância da coluna </returns>
        public static ColumnInfo CreatePrimaryKeyColumn(string columnName, Type type, bool autoIncremento, int? namePropertyIndex)
        {
            return new ColumnInfo(columnName, type, false, true, autoIncremento, namePropertyIndex, null);
        }



        #endregion

        #region Construtores
        private ColumnInfo(string columnName, Type type)
            : this(columnName, type, true, false, false, null, null)
        {
        }

        private ColumnInfo(string columnName, Type type, bool nullable)
            : this(columnName, type, nullable, false, false, null, null)
        {
        }

        private ColumnInfo(string columnName, Type type, bool key, bool autoInc)
            : this(columnName, type, false, key, autoInc, null, null)
        {
        }

        private ColumnInfo(string columnName, Type type, bool nullable, int? namePropertyIndex)
            : this(columnName, type, nullable, false, false, namePropertyIndex, null)
        {
        }

        private ColumnInfo(string columnName, Type type, object defaultValue)
            : this(columnName, type, true, false, false, null, defaultValue)
        {
        }

        private ColumnInfo(string columnName, Type type, bool nullable, bool key, bool autoInc, int? namePropertyIndex, object defaultValue)
        {
            this.ColumnName = columnName;
            this.PropertyType = type;
            this.IsNullable = nullable;
            this.IsKey = key;
            this.ColumnType = DataAccess.MapColumnType(type);
            this.AutoIncrement = autoInc;
            this.NamePropertyIndex = namePropertyIndex.GetValueOrDefault(-1);
            this.DefaultValue = defaultValue;
            
        }
        #endregion

        internal DataAccessParameter MakeParameter(object value)
        {
            return new DataAccessParameter(this.ColumnName, value, this.ColumnType);
        }
    }
}